package com.drg.center.service;

import com.drg.center.dao.*;
import com.drg.center.entity.*;
import com.drg.center.entity.result.GroupPredictionVO;
import com.guaike.core.utils.BigDecimalUtil;
import lombok.AllArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
@AllArgsConstructor
public class BaseDealService {
    private final DictDiagnosisMainDAO dictDiagnosisMainDAO;
    private final DictDiagnosisDAO dictDiagnosisDAO;
    private final DictDrgDAO dictDrgDAO;
    private final DictMccDAO dictMccDAO;
    private final DictCcDAO dictCcDAO;
    private final DictDiagnosisMainWithoutDAO dictDiagnosisMainWithoutDAO;
    private final DictAdrgDAO dictAdrgDAO;
    private final DrgPatientCaseOutDAO drgPatientCaseOutDAO;
    private final DrgPatientCaseDAO drgPatientCaseDAO;

    /**
     * CHS入组预测
     *
     * @param sex
     * @param age
     * @param ageDay
     * @param medicareType
     * @param totalCost
     * @param inpatientDays
     * @param diagnosisCode
     * @param operationCode
     * @param diagnosisCodeList
     * @param operationCodeList
     * @return
     */
    public GroupPredictionVO groupPrediction(Integer sex, Integer age, Integer ageDay
            , String medicareType, BigDecimal totalCost, Integer inpatientDays, String diagnosisCode
            , String operationCode, List<String> diagnosisCodeList, List<String> operationCodeList) {
        return dealDrgGroup(sex, age, ageDay, medicareType, totalCost, inpatientDays, diagnosisCode, operationCode, diagnosisCodeList, operationCodeList);
    }

    public GroupPredictionVO dealDrgGroup(Integer sex, Integer age, Integer ageDay
            , String medicareType, BigDecimal totalCost, Integer inpatientDays, String diagnosisCode
            , String operationCode, List<String> diagnosisCodeList, List<String> operationCodeList) {
        GroupPredictionVO vo = new GroupPredictionVO();
        vo.setInpatientDays(inpatientDays);
        String mdcCode = null;
        if (StringUtils.isNotBlank(operationCode)) {
            List<DictDiagnosisPO> mdca = dictDiagnosisDAO.findByMdcAndMain("MDCA", operationCode);
            if (CollectionUtils.isNotEmpty(mdca)) {
                mdcCode = "MDCA";
            }
        }

        if (StringUtils.isBlank(mdcCode)) {
            if (Objects.nonNull(ageDay) && ageDay < 29) {
                mdcCode = "MDCP";
            }
        }
        if (StringUtils.isBlank(mdcCode)) {
            DictDiagnosisMainPO mainPO = dictDiagnosisMainDAO.findByMdcAndMain("MDCY", diagnosisCode);
            if (Objects.nonNull(mainPO)) {
                mdcCode = "MDCY";
            }
        }
        if (StringUtils.isBlank(mdcCode)) {
            DictDiagnosisMainPO mainPO = dictDiagnosisMainDAO.findByMdcAndMain("MDCZ", diagnosisCode);
            if (Objects.nonNull(mainPO)) {
                mdcCode = "MDCZ";
            }
        }
        if (StringUtils.isBlank(mdcCode)) {
            DictDiagnosisMainPO mainPO = dictDiagnosisMainDAO.findByMain(diagnosisCode);
            if (Objects.nonNull(mainPO)) {
                mdcCode = mainPO.getMdcCode();
            }
        }
        if (StringUtils.isNotBlank(mdcCode) && mdcCode.equals("MDCM")) {
            if (!sex.equals(1)) {
                vo.setDrgCode("MQY");
                vo.setDrgName("与主要诊断无关的手术");
                vo.setMarkRed("不能作为女性诊断");
                DictDrgPO drgQyPO = dictDrgDAO.findOne(DictDrgPO::getDrgCode, vo.getDrgCode());
                if (Objects.nonNull(drgQyPO)) {
                    BigDecimal qyOffset = totalCost.subtract(drgQyPO.getDrgCostStandard());
                    vo.setDrgCostStandard(drgQyPO.getDrgCostStandard());
                    vo.setCostOffset(qyOffset);
                    vo.setIsBase(drgQyPO.getIsBaseDisease());
                    vo.setWeight(drgQyPO.getDrgWeight().toPlainString());
                    vo.setRate(drgQyPO.getDrgRate().toPlainString());
                }
                return vo;
            }
        }
        if (StringUtils.isNotBlank(mdcCode) && mdcCode.equals("MDCN")) {
            if (!sex.equals(2)) {
                vo.setDrgCode("NQY");
                vo.setDrgName("与主要诊断无关的手术");
                vo.setMarkRed("不能作为男性诊断");
                DictDrgPO drgQyPO = dictDrgDAO.findOne(DictDrgPO::getDrgCode, vo.getDrgCode());
                if (Objects.nonNull(drgQyPO)) {
                    BigDecimal qyOffset = totalCost.subtract(drgQyPO.getDrgCostStandard());
                    vo.setDrgCostStandard(drgQyPO.getDrgCostStandard());
                    vo.setCostOffset(qyOffset);
                    vo.setIsBase(drgQyPO.getIsBaseDisease());
                    vo.setWeight(drgQyPO.getDrgWeight().toPlainString());
                    vo.setRate(drgQyPO.getDrgRate().toPlainString());
                }
                return vo;
            }
        }
        DictDrgPO drgNonePO = dictDrgDAO.findOne(DictDrgPO::getDrgCode, "0000");
        BigDecimal noneOffset = totalCost.subtract(drgNonePO.getDrgCostStandard());
        if (StringUtils.isBlank(mdcCode)) {
            vo.setDrgCode(drgNonePO.getDrgCode());
            vo.setDrgName(drgNonePO.getDrgName());
            vo.setDrgCostStandard(drgNonePO.getDrgCostStandard());
            vo.setCostOffset(noneOffset);
            vo.setIsBase(drgNonePO.getIsBaseDisease());
            vo.setWeight(drgNonePO.getDrgWeight().toPlainString());
            vo.setRate(drgNonePO.getDrgRate().toPlainString());
            vo.setMarkRed("不符合MDC入组条件，无法入组");
        } else {
            if (StringUtils.isNotBlank(operationCode)) {
                char c = mdcCode.charAt(3);
                String drgCode = c + "QY";
                List<DictDiagnosisPO> pos = dictDiagnosisDAO.findByMdcAndMain(mdcCode, operationCode);
                if (CollectionUtils.isEmpty(pos)) {
                    vo.setDrgCode(drgCode);
                    vo.setDrgName("与主要诊断无关的手术");
                    DictDrgPO drgQyPO = dictDrgDAO.findOne(DictDrgPO::getDrgCode, vo.getDrgCode());
                    if (Objects.nonNull(drgQyPO)) {
                        BigDecimal qyOffset = totalCost.subtract(drgQyPO.getDrgCostStandard());
                        vo.setDrgCostStandard(drgQyPO.getDrgCostStandard());
                        vo.setCostOffset(qyOffset);
                        vo.setIsBase(drgQyPO.getIsBaseDisease());
                        vo.setWeight(drgQyPO.getDrgWeight().toPlainString());
                        vo.setRate(drgQyPO.getDrgRate().toPlainString());
                    }
                    return vo;
                }
            }
            List<DictDiagnosisPO> dictDiagnosisPOS = null;
            if (StringUtils.isNotBlank(operationCode)) {
                dictDiagnosisPOS = dictDiagnosisDAO.findByMdcAndMain(mdcCode, operationCode);
            }
            if (CollectionUtils.isEmpty(dictDiagnosisPOS)) {
                dictDiagnosisPOS = dictDiagnosisDAO.findByMdcAndMain(mdcCode, diagnosisCode);
            }
            if (CollectionUtils.isNotEmpty(dictDiagnosisPOS) && dictDiagnosisPOS.size() == 1) {
                DictDiagnosisPO dictDiagnosisPO = dictDiagnosisPOS.get(0);
                DictAdrgPO adrgPO = dictAdrgDAO.findOne(DictAdrgPO::getAdrgCode, dictDiagnosisPO.getAdrgCode());
                if (CollectionUtils.isNotEmpty(diagnosisCodeList)) {
                    List<DictMccPO> mccPOS = dictMccDAO.findIn(DictMccPO::getDiagnosisCode, diagnosisCodeList);
                    List<DictCcPO> ccPOS = dictCcDAO.findIn(DictCcPO::getDiagnosisCode, diagnosisCodeList);
                    if (CollectionUtils.isEmpty(mccPOS) && CollectionUtils.isEmpty(ccPOS)) {
                        vo.setDrgCode(dictDiagnosisPO.getAdrgCode() + "9");
                        vo.setDrgName(adrgPO.getAdrgName());
                        DictDrgPO drgNinePO = dictDrgDAO.findOne(DictDrgPO::getDrgCode, vo.getDrgCode());
                        if (Objects.nonNull(drgNinePO)) {
                            BigDecimal nineOffset = totalCost.subtract(drgNinePO.getDrgCostStandard());
                            vo.setDrgCostStandard(drgNinePO.getDrgCostStandard());
                            vo.setCostOffset(nineOffset);
                            vo.setIsBase(drgNinePO.getIsBaseDisease());
                            vo.setWeight(drgNinePO.getDrgWeight().toPlainString());
                            vo.setRate(drgNinePO.getDrgRate().toPlainString());
                        }
                    } else {
                        List<String> list = new ArrayList<>();
                        if (CollectionUtils.isNotEmpty(mccPOS)) {
                            List<String> collect = mccPOS.stream().map(DictMccPO::getWithoutTable).collect(Collectors.toList());
                            list.addAll(collect);
                        }
                        if (CollectionUtils.isNotEmpty(ccPOS)) {
                            List<String> collect = ccPOS.stream().map(DictCcPO::getWithoutTable).collect(Collectors.toList());
                            list.addAll(collect);
                        }
                        DictDiagnosisMainWithoutPO withoutPO = dictDiagnosisMainWithoutDAO.findOneWith(diagnosisCode, list);
                        if (Objects.nonNull(withoutPO)) {
                            vo.setDrgCode(dictDiagnosisPO.getAdrgCode() + "5");
                            vo.setDrgName(adrgPO.getAdrgName() + "，不伴并发症或合并症");
                            DictDrgPO drgFivePO = dictDrgDAO.findOne(DictDrgPO::getDrgCode, vo.getDrgCode());
                            if (Objects.nonNull(drgFivePO)) {
                                BigDecimal nineOffset = totalCost.subtract(drgFivePO.getDrgCostStandard());
                                vo.setDrgCostStandard(drgFivePO.getDrgCostStandard());
                                vo.setCostOffset(nineOffset);
                                vo.setIsBase(drgFivePO.getIsBaseDisease());
                                vo.setWeight(drgFivePO.getDrgWeight().toPlainString());
                                vo.setRate(drgFivePO.getDrgRate().toPlainString());
                            }
                        } else {
                            if (CollectionUtils.isNotEmpty(mccPOS)) {
                                vo.setDrgCode(dictDiagnosisPO.getAdrgCode() + "1");
                                vo.setDrgName(adrgPO.getAdrgName() + "，伴严重并发症或合并症");
                                DictDrgPO drgOnePO = dictDrgDAO.findOne(DictDrgPO::getDrgCode, vo.getDrgCode());
                                BigDecimal oneOffset = totalCost.subtract(drgOnePO.getDrgCostStandard());
                                vo.setDrgCostStandard(drgOnePO.getDrgCostStandard());
                                vo.setCostOffset(oneOffset);
                                vo.setIsBase(drgOnePO.getIsBaseDisease());
                                vo.setWeight(drgOnePO.getDrgWeight().toPlainString());
                                vo.setRate(drgOnePO.getDrgRate().toPlainString());
                            } else {
                                vo.setDrgCode(dictDiagnosisPO.getAdrgCode() + "3");
                                vo.setDrgName(adrgPO.getAdrgName() + "，伴并发症或合并症");
                                DictDrgPO drgThreePO = dictDrgDAO.findOne(DictDrgPO::getDrgCode, vo.getDrgCode());
                                BigDecimal threeOffset = totalCost.subtract(drgThreePO.getDrgCostStandard());
                                vo.setDrgCostStandard(drgThreePO.getDrgCostStandard());
                                vo.setCostOffset(threeOffset);
                                vo.setIsBase(drgThreePO.getIsBaseDisease());
                                vo.setWeight(drgThreePO.getDrgWeight().toPlainString());
                                vo.setRate(drgThreePO.getDrgRate().toPlainString());
                            }
                        }
                    }
                } else {
                    vo.setDrgCode(dictDiagnosisPO.getAdrgCode() + "9");
                    vo.setDrgName(adrgPO.getAdrgName());
                    DictDrgPO drgNinePO = dictDrgDAO.findOne(DictDrgPO::getDrgCode, vo.getDrgCode());
                    if (Objects.nonNull(drgNinePO)) {
                        BigDecimal nineOffset = totalCost.subtract(drgNinePO.getDrgCostStandard());
                        vo.setDrgCostStandard(drgNinePO.getDrgCostStandard());
                        vo.setCostOffset(nineOffset);
                        vo.setIsBase(drgNinePO.getIsBaseDisease());
                        vo.setWeight(drgNinePO.getDrgWeight().toPlainString());
                        vo.setRate(drgNinePO.getDrgRate().toPlainString());
                    }
                }
            } else {
                vo.setDrgCode(drgNonePO.getDrgCode());
                vo.setDrgName(drgNonePO.getDrgName());
                vo.setMarkRed("不符合MDC入组条件，无法入组");
                vo.setDrgCostStandard(drgNonePO.getDrgCostStandard());
                vo.setCostOffset(noneOffset);
                vo.setIsBase(drgNonePO.getIsBaseDisease());
                vo.setWeight(drgNonePO.getDrgWeight().toPlainString());
                vo.setRate(drgNonePO.getDrgRate().toPlainString());
            }
        }
        return vo;
    }

    /**
     * 计算基准点数
     *
     * @return
     */
    public String calculateReferencePoints(String drgCode) {
        BigDecimal avgCost = drgPatientCaseOutDAO.avgInHospitalCost(null);
        BigDecimal drgAvgCost = drgPatientCaseOutDAO.avgInHospitalCost(drgCode);
        BigDecimal referencePoints = drgAvgCost.divide(avgCost, 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100));
        return BigDecimalUtil.formatBigDecimal(referencePoints);
    }

    /**
     * 计算费用倍率
     *
     * @return
     */
    public String calculateCostMultiplier(String drgCode) {
        BigDecimal avgCost = drgPatientCaseOutDAO.avgCost(null);
        BigDecimal drgAvgCost = drgPatientCaseOutDAO.avgCost(drgCode);
        BigDecimal referencePoints = drgAvgCost.divide(avgCost, 2, BigDecimal.ROUND_HALF_UP);
        return BigDecimalUtil.formatBigDecimal(referencePoints);
    }
}
